package com.itheima.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.wms.common.constants.CodeConstant;
import com.itheima.wms.common.enums.*;
import com.itheima.wms.common.service.CrudServiceImpl;
import com.itheima.wms.dao.*;
import com.itheima.wms.entity.*;
import com.itheima.wms.factory.CodeWorker;
import com.itheima.wms.service.PickingService;
import com.itheima.wms.service.StatusRecordService;
import com.itheima.wms.service.StockService;
import com.itheima.wms.vo.BatchVO;
import com.itheima.wms.vo.PickingDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 业务实现类
 * 拣货任务
 * </p>
 */
@Slf4j
@Service
public class PickingServiceImpl extends CrudServiceImpl<PickingMapper, PickingEntity> implements PickingService {

    @Autowired
    private HandoverMapper handoverMapper;
    @Autowired
    private OutboundMapper outboundMapper;
    @Autowired
    private OutboundListMapper outboundListMapper;
    @Autowired
    private StatusRecordService statusRecordService;
    @Autowired
    private StockService stockService;
    @Autowired
    private StockRecordMapper stockRecordMapper;

    @Override
    @Transactional
    public BatchVO complete(List<Long> ids) {
        BatchVO.BatchVOBuilder batchVOBuilder = BatchVO.builder();
        ids.forEach(id -> {
            PickingEntity pickingEntity = this.getById(id);

            // 校验清单是否有未填写的
            LambdaQueryWrapper<OutboundListEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OutboundListEntity::getMasterId, pickingEntity.getMasterId());
            List<OutboundListEntity> outboundListEntities = outboundListMapper.selectList(wrapper);
            outboundListEntities = outboundListEntities.stream().filter(item -> null != item.getPickingNum()).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(outboundListEntities)) {
                log.info("id:{} 清单未填写完成", id);
                batchVOBuilder.error(pickingEntity.getCode() + "未完成拣货确认");
                return;
            }

            if (PickingStatus.PICKING.getCode() != pickingEntity.getStatus()) {
                log.info("id:{} 状态不正确", id);
                batchVOBuilder.error(pickingEntity.getCode() + "状态不合法");
                return;
            }

            LambdaQueryWrapper<HandoverEntity> handoverWrapper = new LambdaQueryWrapper<>();
            handoverWrapper.eq(HandoverEntity::getMasterId, pickingEntity.getMasterId());
            Integer handoverCount = handoverMapper.selectCount(handoverWrapper);
            if (handoverCount > 0) {
                log.info("id:{} 已存在交接任务", id);
                batchVOBuilder.error(pickingEntity.getCode() + "已生成过交接任务");
                return;
            }

            // 修改拣货任务状态 为 拣选完成
            pickingEntity.setStatus(PickingStatus.COMPLETED.getCode());
            pickingEntity.setCompletionTime(LocalDateTime.now());
            this.updateById(pickingEntity);
            statusRecordService.saveStatus(pickingEntity);

            // 修改出库单状态 为 拣选完成
            OutboundEntity outboundEntity = outboundMapper.selectById(pickingEntity.getMasterId());
            outboundEntity.setStatus(OutboundStatus.PICKING_COMPLETED.getCode());
            outboundMapper.updateById(outboundEntity);
            statusRecordService.saveStatus(outboundEntity);

            //  生成损益  和产品确认 不需要生成损益。

            // 生成交接任务
            HandoverEntity handoverEntity = new HandoverEntity();
            BeanUtils.copyProperties(pickingEntity, handoverEntity);
            BeanUtils.copyProperties(outboundEntity, handoverEntity);
            handoverEntity.setMasterId(outboundEntity.getId());
            handoverEntity.setCode(CodeWorker.nextCode(CodeConstant.HANDOVER));
            handoverEntity.setStatus(HandoverStatus.NEW.getCode());  //初始状态
            handoverEntity.setId(null);
            handoverMapper.insert(handoverEntity);
            statusRecordService.saveStatus(handoverEntity);

            // 修改出库单状态 为 交接中
            outboundEntity.setStatus(OutboundStatus.HANDOVER.getCode());
            outboundMapper.updateById(outboundEntity);
            statusRecordService.saveStatus(outboundEntity);

            // 减库存 （之前已经被冻结） 直接修改冻结库存 总库存即可
            subStock(outboundListEntities);

            batchVOBuilder.result(handoverEntity.getCode());
        });
        return batchVOBuilder.build();
    }

    /**
     * 减库存
     *
     * @param outboundListEntities
     */
    private void subStock(List<OutboundListEntity> outboundListEntities) {
        outboundListEntities.forEach(outboundListEntity -> {
            Long stockId = outboundListEntity.getStockId();
            Integer dbPickingNum = outboundListEntity.getPickingNum();

            StockEntity stockEntity = stockService.getById(stockId);
            Integer original = stockEntity.getTotal();
            Integer originalFree = stockEntity.getFree();

            stockEntity.setFrozen(stockEntity.getFrozen() - dbPickingNum);
            stockEntity.setTotal(stockEntity.getFree() + stockEntity.getFrozen());
            stockService.saveOrUpdate(stockEntity);

            StockRecordEntity stockRecordEntity = new StockRecordEntity();
            stockRecordEntity.setSourceId(outboundListEntity.getId());
            stockRecordEntity.setLocationId(stockEntity.getLocationId());
            stockRecordEntity.setType(StockRecordType.JH.getCode());// 拣货
            stockRecordEntity.setOriginal(original);
            stockRecordEntity.setOriginalFree(originalFree);
            stockRecordEntity.setWay(StockRecordWay.NEGATIVE.getCode());
            stockRecordEntity.setAlteration(dbPickingNum);
            stockRecordEntity.setResult(stockEntity.getTotal());
            stockRecordEntity.setResultFree(stockEntity.getFree());
            stockRecordMapper.insert(stockRecordEntity);
        });
    }

    @Override
    public IPage<PickingDetailVO> pageDetail(Page<PickingDetailVO> page, Map data) {
        IPage<PickingDetailVO> iPage = this.baseMapper.selectPickingDetail(page, data);
        return iPage;
    }
}

